using System;
using System.Collections.Generic;
using Moq;
using NUnit.Framework;
using OSCSchema;

namespace OSC.Base.Tests
{
    [TestFixture]
    public class CachedSessionTest
    {
        private CachedSession m_CachedSession;
        private Mock<ICachingStrategy> m_MockCaching;
        private Mock<ISocialConnector> m_MockSession;
        private Mock<IConverter<IPerson, personType>> m_MockPersonConverter;
        private Mock<IConverter<IActivity, activityDetailsType>> m_MockActivityConverter;
        private Mock<IConverter<IActivityTemplate, activityTemplateContainerType>> m_MockActivityTempleteConverter;
        [SetUp]
        public void SetUp()
        {
            m_MockSession = new Mock<ISocialConnector>(MockBehavior.Strict);
            m_MockCaching = new Mock<ICachingStrategy>(MockBehavior.Strict);
            m_MockPersonConverter = new Mock<IConverter<IPerson, personType>>(MockBehavior.Strict);
            m_MockActivityConverter = new Mock<IConverter<IActivity, activityDetailsType>>(MockBehavior.Strict);
            m_MockActivityTempleteConverter = new Mock<IConverter<IActivityTemplate, activityTemplateContainerType>>(MockBehavior.Strict);

            m_MockSession.SetupGet(m => m.SiteUrl).Returns("siteurl").AtMostOnce();

            m_CachedSession = new CachedSession(m_MockSession.Object, m_MockCaching.Object, m_MockPersonConverter.Object, null, m_MockActivityTempleteConverter.Object);
        }
        [TearDown]
        public void TearDown()
        {
            m_MockSession.VerifyAll();
            m_MockCaching.VerifyAll();
            m_MockPersonConverter.VerifyAll();
            m_MockActivityConverter.VerifyAll();
            m_MockActivityTempleteConverter.VerifyAll();
        }

        [Test]
        public void TestLogon_CallsLogonOnTheSessionImplementation()
        {
            var mockPerson = new Mock<IPerson>();
            var foo = string.Empty;
            m_MockSession.Setup(m => m.Logon("foo", "bar", out foo)).Returns(mockPerson.Object).AtMostOnce();

            m_CachedSession.Logon("foo", "bar");
        }
        [Test]
        public void TestLogonWeb_ShouldThrowException()
        {
            var connectIn = string.Empty;
            string connectOut;
            try
            {
                m_CachedSession.LogonWeb(connectIn, out connectOut);
                Assert.Fail();
            }
            catch (NotImplementedException) { }
        }
        [Test]
        public void TestGetLogonUrl_ReturnsTheLogonUrlOfSession()
        {
            m_MockSession.SetupGet(m => m.LogonUrl).Returns("foourl").AtMostOnce();
            var url = m_CachedSession.GetLogonUrl();
            Assert.AreEqual("foourl", url);
        }
        [Test]
        public void TestGetNetworkIdentifier_ReturnsTheLogonUrlOfSession()
        {
            m_MockSession.SetupGet(m => m.LogonUrl).Returns("foourl").AtMostOnce();
            var url = m_CachedSession.GetNetworkIdentifier();
            Assert.AreEqual("foourl", url);
        }
        [Test]
        public void TestGetLoggedOnUser_ReturnsTheLoggedOnProfile()
        {
            var profile = m_CachedSession.GetLoggedOnUser();
            Assert.IsNotNull(profile);
        }
        [Test]
        public void TestGetPerson_ReturnsISociaPerson()
        {
            var mockPerson = new Mock<IPerson>();
            m_MockCaching.Setup(m => m.GetPerson("userId")).Returns(mockPerson.Object).AtMostOnce();
            var person = m_CachedSession.GetPerson("userId");
            Assert.IsNotNull(person);
        }
        [Test]
        public void TestFindPerson_ReturnsAStringWithFriends()
        {
            var personList = new List<IPerson>
                                 {
                                     new Mock<IPerson>().Object,
                                     new Mock<IPerson>().Object
                                 };
            //m_MockCaching.Setup(m => m.FindPerson("fooId")).Returns(personList);
            m_MockPersonConverter.Setup(m => m.Convert(It.IsAny<IPerson>())).Returns(new personType()).AtMost(2);
            var friends = m_CachedSession.FindPerson("fooId");

            Assert.IsNotNull(friends);
        }
        [Test]
        public void TestGetActivities_ShouldThrowException()
        {
            try
            {
                m_CachedSession.GetActivities(null, new DateTime());
                Assert.Fail();
            }
            catch (NotImplementedException) { }
        }
        [Test]
        public void TestFollowPerson_ShouldThrowException()
        {
            try
            {
                m_CachedSession.FollowPerson(string.Empty);
                Assert.Fail();
            }
            catch (NotImplementedException) { }
        }
        [Test]
        public void TestUnFollowPerson_CallsSessionUnfollow()
        {
            m_MockSession.Setup(m => m.Unfollow("unfollowId")).AtMostOnce();
            m_CachedSession.UnFollowPerson("unfollowId");
        }
        [Test]
        public void TestGetPeopleDetails_ShouldGetAFriendsString()
        {
            /* var hashedAddresses = m_Serializer.Deserialize<hashedAddresses>(personsAddresses);
               var userIds = hashedAddresses.personAddresses.Select(m => m_CachingStrategy.GetUserId(m.hashedAddress));
               var persons = userIds.Select(id => m_CachingStrategy.GetPerson(m_Session, id))
                                    .Select(m_PersonConverter.Convert)
                                    .ToArray();
               var friends = new friends { person = persons };
               return m_Serializer.Serialize(friends);*/
        }
        [Test]
        public void TestGetActivitiesEx_ShouldReturnActivitiesFeed()
        {
            var acts = new List<IActivity>
                                 {
                                     new Mock<IActivity>().Object,
                                     new Mock<IActivity>().Object
                                 };
            m_MockSession.SetupGet(m => m.SiteUrl).Returns("https://foo").AtMostOnce();
            m_MockSession.Setup(m => m.GetActivityTemplate()).Returns(new ActivityTemplate()).AtMostOnce();
            m_MockCaching.Setup(m => m.GetUserId(new[] { "foo", "bar" })).Returns("foouser").AtMostOnce();
            m_MockCaching.Setup(m => m.GetActivities("foouser", new DateTime())).Returns(acts).AtMostOnce();
            m_MockActivityConverter.Setup(m => m.Convert(It.IsAny<IActivity>())).Returns(new activityDetailsType()).AtMost(2);
            m_MockActivityTempleteConverter.Setup(m => m.Convert(It.IsAny<IActivityTemplate>())).Returns(new activityTemplateContainerType()).AtMostOnce();

            var activities = m_CachedSession.GetActivitiesEx(new[] { "foo", "bar" }, new DateTime());
            Assert.IsNotNull(activities);
        }
        [Test]
        public void TestFollowPersonEx_ShouldFollowAPerson()
        {
            m_MockSession.Setup(m => m.Follow(null, null)).AtMostOnce();
            m_CachedSession.FollowPersonEx(null, null);
        }
    }
}